package ws

import (
	"bufio"
	"fmt"
	"github.com/gorilla/websocket"
	uuid "github.com/satori/go.uuid"
	"go-jsmpeg-server/config"
	"go-jsmpeg-server/util"
	"net/http"
	"strconv"
	"strings"
)

func StartWebSocketServer(port int) {
	util.Logger().Infof("start http server on port = %d\n", port)

	pushPaths := config.Config.PushPaths
	for _, path := range pushPaths {
		pushPath := fmt.Sprintf("/push%s", path)
		http.HandleFunc(pushPath, push)
		util.Logger().Infof("push path = %s\n", pushPath)
	}
	// http.HandleFunc("/push/test", push)

	livePaths := config.Config.LivePaths
	for _, path := range livePaths {
		livePath := fmt.Sprintf("/live%s", path)
		http.HandleFunc(livePath, live)
		util.Logger().Infof("live path = %s\n", livePath)
	}
	// http.HandleFunc("/live/test", live)

	go wsManager.StartWebSocketManager()

	err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
	if err != nil {
		util.Logger().Errorf("start http err: %v\n", err)
	}
}

func push(w http.ResponseWriter, r *http.Request) {

	clone := r.Header.Clone()

	for s := range clone {
		util.Logger().Info("%s\n", s)
	}

	path := r.URL.Path
	index := strings.LastIndex(path, "/")

	groupId := path[1+index:]
	util.Logger().Debugf("start push groupId = %s\n", groupId)

	reader := bufio.NewReader(r.Body)
	for {
		data, err := reader.ReadBytes('\n')
		if err != nil {
			break
		}
		wsManager.GroupBroadcast(groupId, data)
	}
	util.Logger().Debugf("stop push groupId = %s\n", groupId)
}

// websocket live view
func live(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")

	path := r.URL.Path
	index := strings.LastIndex(path, "/")

	groupId := path[1+index:]

	upgrader := websocket.Upgrader{
		Subprotocols: []string{r.Header.Get("Sec-WebSocket-Protocol")},
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		util.Logger().Errorf("[ws] upgrade: %v\n", err)
		return
	}

	v4, err := uuid.NewV4()
	if err != nil {
		util.Logger().Errorf("[ws] uuid v4 error: %v\n", err)
		return
	}

	wsClientId := v4.String()
	util.Logger().Infof("[ws-live] groupId = %s. remoteAddr = %s. wsClientId = %s\n", groupId, r.RemoteAddr, wsClientId)

	client := &WsClientConn{
		Id:    wsClientId,
		Group: groupId,
		Conn:  c,
		Send:  make(chan []byte, 2048),
	}

	wsManager.registerClient(client)

	go client.Read()
	go client.Write()

}
